package edu.towson.cosc.cosc455.jsmole1.markdowncompiler;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;

public class SuperHappyFuntimeCompiler {
	
	/** Arraylist that represents the parse tree **/
	public static ArrayList<String> parseTree = new ArrayList<String>();
	
	/** Arraylist that handles all variable uses and definitions **/
	public static ArrayList<String> variableTree = new ArrayList<String>();
	
	private static SuperHappyFuntimeLexicalAnalyzer lexer;
	private static SuperHappyFuntimeSyntaxAnalyzer shfsa;
	
	/** Change to true to view debugging statements */
	public static boolean debugStatements = false;
	
	public static void main(String[] args) {
		
		// Check to make sure there are args
		if (args.length == 0)
			System.out.println("You must select a file");
		
		else {
			// Check to make sure the file has an mkd extension --> endsWith(".mkd")
			String runtimeFile = args[0];
			if (runtimeFile.endsWith(".mkd")) {
				
				if (debugStatements)
					System.out.println("File ends with mkd");
				
				// Read runtime mkd file
				try {
					SuperHappyFuntimeLexicalAnalyzer.bigString = readFile(runtimeFile, StandardCharsets.UTF_8);
					if (debugStatements)
						System.out.println(SuperHappyFuntimeLexicalAnalyzer.bigString + "\n\n\n");
				} catch (IOException e) {}
				
				
				// Call the lexical analyzer to get the first token set
				lexer = new SuperHappyFuntimeLexicalAnalyzer();
				lexer.getNextToken();

				
				// Call the document() to begin parsing
				shfsa = new SuperHappyFuntimeSyntaxAnalyzer();
				try {
					if (debugStatements)
						System.out.println("Calling document() method");
					
					shfsa.document();
					
					if (debugStatements)
						System.out.println("\n\n--------");
					
				} catch (CompilerException e) {}
				
				if (debugStatements) {
					for (int i = 0; i < parseTree.size(); i++)
						System.out.println(parseTree.get(i) + "-");
				}
				
				writeToHTML();
				
			} else
				System.out.println("You must select an .mkd file");
		}
		
	}
	
	// http://stackoverflow.com/a/326440/1097170
	public static String readFile(String path, Charset encoding) throws IOException {
		byte[] encoded = Files.readAllBytes(Paths.get(path));
		return encoding.decode(ByteBuffer.wrap(encoded)).toString();
	}
	
	// Write html file
	// http://stackoverflow.com/a/6327951/1097170
	public static void writeToHTML() {
		
		File f = new File("SuperHappyFuntime.html");
		BufferedWriter bw;
		try {
			bw = new BufferedWriter(new FileWriter(f));
			
			// Loop through our markdown parsetree
			for (int i = 0; i < parseTree.size(); i++) {
				
				// Plain text case
				if (!(parseTree.get(i).contains("#"))) {
					
					// If tag is just plain 'ol text
					bw.write(parseTree.get(i).toString());

					// If previous tag is Audio...
					if (parseTree.get(i - 1).equalsIgnoreCase(Tag.STARTAUDIO))
						bw.write("<source src=\"" + parseTree.get(i) + "\">");
					
					// If previous tag is video...
					else if (parseTree.get(i - 1).equalsIgnoreCase(Tag.STARTVIDEO))
						bw.write("<iframe src=\"" + parseTree.get(i) + "\">");
					
					// TODO should all of these be contains() instead?
				} else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.STARTDOC))
					bw.write("<html>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.ENDDOC))
					bw.write("</html>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.STARTHEAD))
					bw.write("<head>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.ENDHEAD))
					bw.write("</head>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.STARTTITLE))
					bw.write("<title>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.ENDTITLE))
					bw.write("</title>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.STARTPAR))
					bw.write("<p>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.ENDPAR))
					bw.write("</p>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.STARTBOLD))
					bw.write("<b>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.ENDBOLD))
					bw.write("</b>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.STARTITALICS))
					bw.write("<i>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.ENDITALICS))
					bw.write("</i>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.STARTLIST))
					bw.write("<ul>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.ENDLIST))
					bw.write("</ul>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.STARTITEM))
					bw.write("<li>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.ENDITEM))
					bw.write("</li>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.STARTAUDIO))
					bw.write("<audio controls>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.ENDAUDIO))
					bw.write("</audio>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.STARTVIDEO))
					bw.write("<video>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.ENDVIDEO))
					bw.write("</video>");
				
				// TODO These probably aren't even written to html
//				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.STARTDEFINE))
//					bw.write("<var>");
//				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.ENDDEFINE))
//					bw.write("</var>");
				
				// TODO
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.STARTUSE))
					bw.write("<var>");
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.ENDUSE))
					bw.write("</var>");
				
				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.NEWLINE))
					bw.write("<br>");
				
				// TODO probably not written to html
//				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.NAME))
//					bw.write("<name>");
				
				// TODO probably not written to html
//				else if (parseTree.get(i).trim().equalsIgnoreCase(Tag.VALUE))
//					bw.write("<value>");
				
			}
			
			bw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

}
